
import * as THREE from "three";
import { PositionComponent } from "../component/PositionComponent";
import { DList } from "../DList";
import { Entity } from "../entity/Entity";
import { EntitySystem } from "../system/EntitySystem";
import { GameObjectSystem } from "../system/GameObjectSystem";
import { InputSystem } from "../system/InputSystem";
import { MoveSystem } from "../system/MoveSystem";

export class GameWorld {
    /**
     * 场景物体
     */
    entityList: DList<Entity> = new DList<Entity>();
    /**
     * 玩家物体
     */
    playerEntityList: DList<Entity> = new DList<Entity>();
    positionList: DList<PositionComponent> = new DList<PositionComponent>();

    private entitySystem: EntitySystem;
    moveSystem: MoveSystem;
    gameObjectSystem: GameObjectSystem;
    private inputSystem: InputSystem;

    mainCamera: THREE.Camera;
    renderer: THREE.WebGLRenderer;
    box: THREE.Mesh;
    scene: THREE.Scene;
    private light: THREE.Light;

    mouseEvent: PointerEvent;

    Start() {
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0x444444);

        this.light = new THREE.HemisphereLight(0xffffff, 0x444444, 1);
        this.light.position.set(- 2, 2, 2);
        this.scene.add(this.light.clone());

        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.setPixelRatio(window.devicePixelRatio);

        this.mainCamera = new THREE.OrthographicCamera();
        this.mainCamera.position.z = 50;

        const geometry = new THREE.BoxBufferGeometry(1, 1.5, 0.1);
        this.box = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial());
        this.scene.add(this.box);
        document.body.appendChild(this.renderer.domElement);

        this.entitySystem = new EntitySystem(this);
        this.moveSystem = new MoveSystem(this);
        this.gameObjectSystem = new GameObjectSystem(this);
        this.inputSystem = new InputSystem(this);

        this.entitySystem.InitScene();
        this.ApplyDelayCommands();//执行延迟增删数组内容的操作

        document.addEventListener("pointermove", (event: PointerEvent) => {
            this.mouseEvent = event;
        });
    }
    Update() {


        //多对多关系
        this.playerEntityList.forEach((player: Entity) => {
            if (player.destroyed)
                return;

            this.inputSystem.Update(player.position);
        });

        //单独遍历某些Component
        this.positionList.forEach((pos: PositionComponent) => {
            if (pos.destroyed)
                return;

            this.moveSystem.Update(pos);
        });

    }

    private ApplyDelayCommands() {
        this.entityList.ApplyDelayCommands();
        this.playerEntityList.ApplyDelayCommands();
        this.positionList.ApplyDelayCommands();
    }

}